package com.guaoran.user.services;

import com.alibaba.dubbo.common.utils.StringUtils;
import com.guaoran.user.IUserCoreService;
import com.guaoran.user.constants.Constants;
import com.guaoran.user.constants.ResponseCodeEnum;
import com.guaoran.user.constants.UserConstants;
import com.guaoran.user.dal.entity.User;
import com.guaoran.user.dal.persistence.UserMapper;
import com.guaoran.user.dto.*;
import com.guaoran.user.exception.ExceptionUtil;
import com.guaoran.user.exception.ServiceException;
import com.guaoran.user.exception.ValidateException;
import com.guaoran.user.utils.JwtTokenUtils;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.SignatureException;
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;


@Service("userCoreService")
public class UserCoreServiceImpl implements IUserCoreService {

    Logger Log = LoggerFactory.getLogger(this.getClass());

    @Autowired
    UserMapper userMapper;
    @Autowired
    RedisTemplate redisTemplate;

    @Override
    public UserLoginResponse login(UserLoginRequest request) {
        Log.info("login request:" + request);
        UserLoginResponse response = new UserLoginResponse();
        try {
            beforeValidate(request);
            User user = userMapper.getUserByUserName(request.getUserName());
            if (user == null || !user.getPassword().equals(request.getPassword())) {
                response.setCode(ResponseCodeEnum.USERORPASSWORD_ERRROR.getCode());
                response.setMsg(ResponseCodeEnum.USERORPASSWORD_ERRROR.getMsg());
                return response;
            }
            //登录成功，保存用户的UID，
            Map<String, Object> map = new HashMap<>();
            map.put("uid", user.getId());
            map.put("exp", DateTime.now().plusDays(1).toDate().getTime() / 1000);
            //根据用户 UID 和 过期时间生成用户 Token
            response.setToken(JwtTokenUtils.generatorToken(map));
            response.setUid(user.getId());
            response.setAvatar(user.getAvatar());
            response.setCode(ResponseCodeEnum.SUCCESS.getCode());
            response.setMsg(ResponseCodeEnum.SUCCESS.getMsg());
        } catch (Exception e) {
            Log.error("login occur exception :" + e);
            ServiceException serviceException = (ServiceException) ExceptionUtil.handlerException4biz(e);
            response.setCode(serviceException.getErrorCode());
            response.setMsg(serviceException.getErrorMessage());
        } finally {
            Log.info("login response->" + response);
        }

        return response;
    }

    @Override
    public CheckAuthResponse validToken(CheckAuthRequest request) {
        CheckAuthResponse response = new CheckAuthResponse();
        try {
            //校验token是否为空
            beforeValidateAuth(request);

            Claims claims = JwtTokenUtils.phaseToken(request.getToken());

            // 此处加上用户校验，解决【无法作废已颁布的令牌/不易应对数据过期。】问题
            // 此处从redis 中取出已经过期的用户，判断用户是否存在，如果不存在则通过，存在则返回已禁用。
            // 该禁用集合是在后台管理进行用户禁用时添加的 todo 暂时没实现

            Boolean member = redisTemplate.opsForSet()
                    .isMember(UserConstants.USER_DISABLED_SET, UserConstants.getUserDisabledRedisKey(claims));
            if(member){
                response.setCode(ResponseCodeEnum.USER_DISABLED.getCode());
                response.setMsg(ResponseCodeEnum.USER_DISABLED.getMsg());
                return response;
            }


            response.setUid(claims.get("uid").toString());
            response.setCode(ResponseCodeEnum.SUCCESS.getCode());
            response.setMsg(ResponseCodeEnum.SUCCESS.getMsg());

        } catch (ExpiredJwtException e) {
            Log.error("Expire :" + e);
            response.setCode(ResponseCodeEnum.TOKEN_EXPIRE.getCode());
            response.setMsg(ResponseCodeEnum.TOKEN_EXPIRE.getMsg());
        } catch (SignatureException e1) {
            Log.error("SignatureException :" + e1);
            response.setCode(ResponseCodeEnum.SIGNATURE_ERROR.getCode());
            response.setMsg(ResponseCodeEnum.SIGNATURE_ERROR.getMsg());
        } catch (Exception e) {
            Log.error("login occur exception :" + e);
            ServiceException serviceException = (ServiceException) ExceptionUtil.handlerException4biz(e);
            response.setCode(serviceException.getErrorCode());
            response.setMsg(serviceException.getErrorMessage());
        } finally {
            Log.info("response:" + response);
        }

        return response;
    }

    /**
     * 注册
     * @param userRegisterRequest
     * @return
     */
    @Transactional
    public UserRegisterResponse register(UserRegisterRequest userRegisterRequest) throws Exception{
        Log.info("begin UserCoreService.register,request:【" + userRegisterRequest + "】");

        UserRegisterResponse response = new UserRegisterResponse();
        try {
            beforeRegisterValidate(userRegisterRequest);

            User user = new User();
            user.setUsername(userRegisterRequest.getUsername());
            user.setPassword(userRegisterRequest.getPassword());
            user.setMobile(userRegisterRequest.getMobile());
            user.setSex(userRegisterRequest.getSex());
            user.setStatus(Constants.NORMAL_USER_STATUS);
            user.setCreateTime(new Date());
            //如果成功，则将UID返回
            int effectRow = userMapper.insertSelective(user);
            if (effectRow > 0) {
                response.setCode(ResponseCodeEnum.SUCCESS.getCode());
                response.setMsg(ResponseCodeEnum.SUCCESS.getMsg());
                response.setUid(user.getId());
                response.setUserBean(user.getId()+"#"+user.getUsername());
                return response;
            }
            response.setCode(ResponseCodeEnum.SYSTEM_BUSY.getCode());
            response.setMsg(ResponseCodeEnum.SYSTEM_BUSY.getMsg());
            return response;
        } catch (Exception e) {
            ServiceException serviceException = (ServiceException) ExceptionUtil.handlerException4biz(e);
            response.setCode(serviceException.getErrorCode());
            response.setMsg(serviceException.getErrorMessage());
            throw e;
        } finally {
            Log.info("register response:【" + response + "】");
        }

    }

    private void beforeRegisterValidate(UserRegisterRequest request) {
        if (null == request) {
            throw new ValidateException("请求对象为空");
        }
        if (StringUtils.isEmpty(request.getUsername())) {
            throw new ValidateException("用户名为空");
        }
        if (StringUtils.isEmpty(request.getPassword())) {
            throw new ValidateException("密码为空");
        }
        if (StringUtils.isEmpty(request.getMobile())) {
            throw new ValidateException("密码为空");
        }
    }

    private void beforeValidateAuth(CheckAuthRequest request) {
        if (request == null) {
            throw new ValidateException("请求对象为空");
        }
        if (StringUtils.isEmpty(request.getToken())) {
            throw new ValidateException("token信息为空");
        }
    }


    private void beforeValidate(UserLoginRequest request) {
        if (request == null) {
            throw new ValidateException("请求对象为空");
        }
        if (StringUtils.isEmpty(request.getUserName())) {
            throw new ValidateException("用户名为空");
        }
        if (StringUtils.isEmpty(request.getPassword())) {
            throw new ValidateException("密码为空");
        }
    }
}
